package com.xxx.user.service.impl;


import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.date.DateUtil;
import cn.hutool.crypto.SecureUtil;
import cn.hutool.jwt.JWTUtil;
import com.alibaba.fastjson2.JSON;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.xxx.common.base.bo.ListResult;
import com.xxx.common.base.bo.UserTokenBO;
import com.xxx.common.web.exception.BusinessException;
import com.xxx.user.dao.mapper.UserMapper;
import com.xxx.user.dao.mapper.UserRoleMapper;
import com.xxx.user.domain.entity.UserDO;
import com.xxx.user.domain.entity.UserRoleDO;
import com.xxx.user.domain.enums.UserErrorCode;
import com.xxx.user.dto.*;
import com.xxx.user.service.UserService;
import lombok.AllArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.ObjectUtils;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Optional;

@Slf4j
@Service
@AllArgsConstructor
public class UserServiceImpl implements UserService {

    private final UserMapper userMapper;
    private final UserRoleMapper userRoleMapper;


    @Override
    public String login(UserDoLoginReqDTO param) {

        UserDO userDO = userMapper.selectOne(new LambdaQueryWrapper<UserDO>()
                .eq(UserDO::getAccount, param.getAccount()), false);

        Optional.ofNullable(userDO).orElseThrow(() -> new BusinessException(UserErrorCode.SYSTEM_ERROR.getCode(), "用户不存在！"));

        if (!userDO.getPassword().equals(SecureUtil.md5(param.getPassword()))) {
            throw new BusinessException(UserErrorCode.SYSTEM_ERROR.getCode(), "密码错误！");
        }

        //查询用户角色信息
        List<UserRoleDO> userRoleDOS = userRoleMapper.selectList(new LambdaQueryWrapper<UserRoleDO>()
                .eq(UserRoleDO::getUserId, userDO.getId()));
        List<Long> roleIds = userRoleDOS.stream().map(UserRoleDO::getUserId).toList();

        UserTokenBO userTokenBO = new UserTokenBO();
        userTokenBO.setUserId(userDO.getId());
        userTokenBO.setUserName(userDO.getUserName());
        userTokenBO.setPhone(userDO.getPhone());
        userTokenBO.setEmail(userDO.getEmail());
        userTokenBO.setRoleIds(roleIds);
        userTokenBO.setExpireTime(DateUtil.nextWeek().toTimestamp().getTime());

        Map<String, Object> map = new HashMap<>();
        map.put("user", JSON.toJSONString(userTokenBO));
        return JWTUtil.createToken(map, "java-projects".getBytes());
    }

    @Override
    @Transactional
    public String create(UserCreateReqDTO param) {

        //判断用户是否存在
        UserDO userDO = userMapper.selectOne(new LambdaQueryWrapper<UserDO>()
                .select(UserDO::getId, UserDO::getUserName)
                .eq(UserDO::getAccount, param.getAccount()), false);
        if (userDO != null) {
            throw new BusinessException(UserErrorCode.SYSTEM_ERROR.getCode(), "用户已经存在！");
        }

        //插入新用户
        UserDO insertUserDO = new UserDO();
        BeanUtil.copyProperties(param, insertUserDO);
        insertUserDO.setPassword(SecureUtil.md5(param.getPassword()));
        userMapper.insert(insertUserDO);

        //插入角色信息
        List<UserRoleDO> userRoleDOS = getUserRoles(param.getRoleList(), insertUserDO.getId());
        userRoleMapper.batchInsert(userRoleDOS);
        return "创建成功！";
    }


    @Override
    @Transactional
    public String update(UserUpdateReqDTO param) {

        UserDO userDO = userMapper.selectOne(new LambdaQueryWrapper<UserDO>()
                .select(UserDO::getId, UserDO::getUserName)
                .eq(UserDO::getAccount, param.getAccount()), false);
        if (userDO != null && !userDO.getId().equals(param.getId())) {
            throw new BusinessException(UserErrorCode.SYSTEM_ERROR.getCode(), "用户已经存在！");
        }

        //更新用户信息
        String password = SecureUtil.md5(param.getPassword());

        UserDO updateUserDO = new UserDO();
        BeanUtil.copyProperties(param, updateUserDO);
        updateUserDO.setPassword(password);
        userMapper.updateById(updateUserDO);

        //更新角色信息
        userRoleMapper.delete(new LambdaQueryWrapper<UserRoleDO>()
                .eq(UserRoleDO::getUserId, param.getId()));
        List<UserRoleDO> userRoleDOS = getUserRoles(param.getRoleList(), param.getId());
        userRoleMapper.batchInsert(userRoleDOS);
        return "更新成功！";
    }

    @Override
    public String delete(List<Long> ids) {
        userMapper.deleteBatchIds(ids);
        return "删除成功！";
    }

    @Override
    public ListResult<UserGetAllResDTO> getAll(UserGetAllReqDTO param) {

        IPage<UserDO> page = new Page<>(param.getPageNum(), param.getPageSize(), param.getIsCount());
        IPage<UserDO> selectPage = userMapper.selectPage(page, new LambdaQueryWrapper<UserDO>()
                .like(!ObjectUtils.isEmpty(param.getUserName()), UserDO::getUserName, param.getUserName())
                .eq(!ObjectUtils.isEmpty(param.getSex()), UserDO::getSex, param.getSex())
                .like(!ObjectUtils.isEmpty(param.getAccount()), UserDO::getAccount, param.getAccount())
                .like(!ObjectUtils.isEmpty(param.getPhone()), UserDO::getPhone, param.getPhone())
                .like(!ObjectUtils.isEmpty(param.getEmail()), UserDO::getEmail, param.getEmail())
                .eq(!ObjectUtils.isEmpty(param.getStatus()), UserDO::getStatus, param.getStatus()));

        List<UserGetAllResDTO> userGetAllResDTOS = selectPage.getRecords().stream()
                .map(it -> {
                    UserGetAllResDTO resDTO = new UserGetAllResDTO();
                    BeanUtil.copyProperties(it, resDTO);
                    return resDTO;
                }).toList();

        ListResult<UserGetAllResDTO> result = new ListResult<>();
        result.setList(userGetAllResDTOS);
        result.setTotalNum((int) selectPage.getTotal());
        return result;
    }

    /*** 数据处理 */
    private List<UserRoleDO> getUserRoles(List<Long> roleList, Long id) {
        return roleList.stream()
                .map(it -> {
                    UserRoleDO userRoleDO = new UserRoleDO();
                    userRoleDO.setUserId(id);
                    userRoleDO.setRoleId(it);
                    return userRoleDO;
                }).toList();
    }

}
